﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;

namespace Drawing
{
    public partial class Form1 : Form
    {
        //biến để thể hiện trạng thái kéo
        private bool m_IsDragging;
        private Point m_StartupPosition;
        private Point m_LastPosition;
        private List<Shapes> m_ListShapes;

        private Shapes m_TempShapes;
        private TypeShape m_Type = (TypeShape)0;

        // Set Pointer Status
        private bool m_IsPointer = true;

        // Color in selected and unselected
        private Color m_Color = Color.Black;

        // Set bool is cut
        private bool m_IsCut = false;
        private bool m_IsCopy = false;

        // Var for cutting
        private Shapes m_Shapes;

        private Color m_ScreenColor;

        public Form1()
        {
            InitializeComponent();
            this.ControlBox = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Reset();

            m_ListShapes = new List<Shapes>();

            this.panel1.MouseDown += new MouseEventHandler(panel1_MouseDown);
            this.panel1.MouseMove += new MouseEventHandler(panel1_MouseMove);
            this.panel1.MouseUp   += new MouseEventHandler(panel1_MouseUp);
            m_ScreenColor = Color.White;
            this.panel1.BackColor = m_ScreenColor;
            this.DoubleBuffered = true;
        }

        private void Reset()
        {
            m_IsDragging = false;
            m_StartupPosition = new Point(0, 0);
            m_LastPosition = new Point(0, 0);
        }

        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            if (m_IsDragging == false && m_IsPointer == false && m_IsCopy == false)
            {
                m_IsDragging = true;
                m_StartupPosition = new Point(e.X, e.Y);
            }
            if (m_IsPointer == true && m_IsCut == false)
            {
                m_IsDragging = false;
                if (m_ListShapes.Count != 0)
                {
                    for (int i = 0; i < m_ListShapes.Count; ++i)
                    {
                        if (m_ListShapes[i].IsContain(new Point(e.X, e.Y)) == true)
                        {
                            m_IsDragging = true;
                            this.panel1.Refresh();
                        }
                        else
                            this.panel1.Refresh();
                    }
                }
            }

            // For cutting
            if ((m_IsCut == true || m_IsCopy == true) && m_Shapes != null )
            {
               
                if (m_Shapes.TypeShape == TypeShape.RECTANGLE)
                {
                    Shapes _t = m_Shapes ;
                    int _Width = m_Shapes.GetRectangle().Width;
                    int _Height = m_Shapes.GetRectangle().Height;
                    m_Shapes = new CRectangle(new Point(e.X, e.Y), _Width, _Height);
                    m_Shapes.TColor = _t.TColor;
                    m_Shapes.SColor = _t.SColor;
                    m_Shapes.Border_Color = _t.Border_Color;
                    //m_Shapes.StartupPosition = new Point(e.X, e.Y);
                    m_ListShapes.Add(m_Shapes);
                    this.panel1.Refresh();
                }
                else if (m_Shapes.TypeShape == TypeShape.CIRCLE)
                {
                    Shapes _t = m_Shapes;
                    int _Width = m_Shapes.GetRectangle().Width;
                    int _Height = m_Shapes.GetRectangle().Height;
                    m_Shapes = new CEllipse(new Point(e.X, e.Y), _Width, _Height);
                    m_Shapes.TColor = _t.TColor;
                    m_Shapes.SColor = _t.SColor;
                    m_Shapes.Border_Color = _t.Border_Color;
                    //m_Shapes.StartupPosition = new Point(e.X, e.Y);
                    m_ListShapes.Add(m_Shapes);

                    this.panel1.Refresh();
                }
                else if (m_Shapes.TypeShape == TypeShape.LINE)
                {
                    Shapes _t = m_Shapes;
                    int _DeltaX = m_Shapes.DeltaX;
                    int _DeltaY = m_Shapes.DeltaY;
                    m_Shapes = new CLine(new Point(e.X, e.Y), _DeltaX, _DeltaY);
                    m_Shapes.TColor = _t.TColor;
                    m_Shapes.SColor = _t.SColor;
                    //m_Shapes.StartupPosition = new Point(e.X, e.Y);
                    m_ListShapes.Add(m_Shapes);

                    this.panel1.Refresh();
                }
                m_IsCut = false;
            }
        }

        private void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (m_IsDragging == true && m_IsPointer == false)
            {
                m_LastPosition = new Point(e.X, e.Y);
                switch (m_Type)
                { 
                    case TypeShape.RECTANGLE:
                        m_TempShapes = new CRectangle(m_StartupPosition, m_LastPosition);
                        break;
                    case TypeShape.CIRCLE:
                        m_TempShapes = new CEllipse(m_StartupPosition, m_LastPosition);
                        break;
                    case TypeShape.LINE:
                        m_TempShapes = new CLine(m_StartupPosition, m_LastPosition);
                        break;
                    case TypeShape.NONE:
                        m_TempShapes = null;
                        break;
                    default:
                        break;
                }

                this.panel1.Refresh();
            }
            else if (m_IsDragging == true && m_IsPointer == true)
            {
                
                for (int i = 0; i < m_ListShapes.Count; ++i)
                {
                    if (m_ListShapes[i].IsSelected == true)
                    {
                        if (m_ListShapes[i].TypeShape == TypeShape.RECTANGLE)
                        {
                            Shapes _t;
                            _t = new CRectangle(new Point(e.X, e.Y), m_ListShapes[i].Width, m_ListShapes[i].Height);
                            _t.SColor = m_ListShapes[i].SColor;
                            _t.Border_Color = m_ListShapes[i].Border_Color;
                            _t.TColor = m_ListShapes[i].TColor;
                            _t.IsSelected = true;
                            m_ListShapes.RemoveAt(i);
                            m_ListShapes.Add(_t);
                            this.panel1.Refresh();
                        }
                        else if(m_ListShapes[i].TypeShape == TypeShape.CIRCLE)
                        {
                            Shapes _t;
                            _t = new CEllipse(new Point(e.X, e.Y), m_ListShapes[i].Width, m_ListShapes[i].Height);
                            _t.SColor = m_ListShapes[i].SColor;
                            _t.Border_Color = m_ListShapes[i].Border_Color;
                            _t.TColor = m_ListShapes[i].TColor;
                            _t.IsSelected = true;
                            m_ListShapes.RemoveAt(i);
                            m_ListShapes.Add(_t);
                            this.panel1.Refresh();
                        }
                        else if (m_ListShapes[i].TypeShape == TypeShape.LINE)
                        {
                            Shapes _t;
                            _t = new CLine(new Point(e.X, e.Y), m_ListShapes[i].DeltaX, m_ListShapes[i].DeltaY);
                            _t.SColor = m_ListShapes[i].SColor;
                            _t.Border_Color = m_ListShapes[i].Border_Color;
                            _t.TColor = m_ListShapes[i].TColor;
                            _t.IsSelected = true;
                            m_ListShapes.RemoveAt(i);
                            m_ListShapes.Add(_t);
                            this.panel1.Refresh();
                        }
                    }
                }
            }
        }

        private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            if (m_IsDragging == true && m_IsPointer == false)
            {
                m_LastPosition = new Point(e.X, e.Y);
                switch (m_Type)
                { 
                    case TypeShape.RECTANGLE:
                        m_TempShapes = new CRectangle(m_StartupPosition, m_LastPosition);
                        break;
                    case TypeShape.CIRCLE:
                        m_TempShapes = new CEllipse(m_StartupPosition, m_LastPosition);
                        break;
                    case TypeShape.LINE:
                        m_TempShapes = new CLine(m_StartupPosition, m_LastPosition);
                        break;
                    case TypeShape.NONE:
                        m_TempShapes = null;
                        break;
                    default:
                        break;
                }

                if(m_TempShapes != null)
                m_ListShapes.Add(m_TempShapes);
                m_TempShapes = null;

            }
            Reset();
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            // Drawing A Line
            Pen blackpen = new Pen(Color.Black, 1);
            Graphics g = e.Graphics;

            if (m_ListShapes.Count != 0)
            {
                for (int i = 0; i < m_ListShapes.Count; ++i)
                {
                    if (m_ListShapes[i].TypeShape == TypeShape.RECTANGLE)
                    {
                        if (m_ListShapes[i].IsSelected == true)
                            g.DrawRectangle(new Pen(Color.Red, 1), m_ListShapes[i].GetRectangle());
                        else if (m_ListShapes[i].TColor == TypeColor.FILL)
                        {
                            SolidBrush _solidBrush = new SolidBrush(m_ListShapes[i].SColor);
                            g.FillRectangle(_solidBrush, m_ListShapes[i].GetRectangle());
                            g.DrawRectangle(new Pen(m_ListShapes[i].Border_Color, 1), m_ListShapes[i].GetRectangle());
                        }
                        else if(m_ListShapes[i].TColor == TypeColor.BORDER)
                        {
                            g.DrawRectangle(new Pen(m_ListShapes[i].SColor, 1), m_ListShapes[i].GetRectangle());
                        }
                    }
                    else if (m_ListShapes[i].TypeShape == TypeShape.CIRCLE)
                    {
                        if (m_ListShapes[i].IsSelected == true)
                            g.DrawEllipse(new Pen(Color.Red, 1), m_ListShapes[i].GetRectangle());
                        else if (m_ListShapes[i].TColor == TypeColor.FILL)
                        {
                            SolidBrush _solidBrush = new SolidBrush(m_ListShapes[i].SColor);
                            g.FillEllipse(_solidBrush, m_ListShapes[i].GetRectangle());
                            g.DrawEllipse(new Pen(m_ListShapes[i].Border_Color, 1), m_ListShapes[i].GetRectangle());
                        }
                        else if (m_ListShapes[i].TColor == TypeColor.BORDER)
                        {
                            g.DrawEllipse(new Pen(m_ListShapes[i].SColor, 1), m_ListShapes[i].GetRectangle());
                        }
                    }
                    else if (m_ListShapes[i].TypeShape == TypeShape.LINE)
                    {
                        if (m_ListShapes[i].IsSelected == true)
                            g.DrawLine(new Pen(Color.Red, 1), m_ListShapes[i].StartupPosition, m_ListShapes[i].LastPosition);
                        else if(m_ListShapes[i].TColor == TypeColor.BORDER)
                            g.DrawLine(new Pen(m_ListShapes[i].SColor, 1), m_ListShapes[i].StartupPosition, m_ListShapes[i].LastPosition);
                    }
                }
            }

            if (m_TempShapes != null)
            {
                if (m_TempShapes.TypeShape == TypeShape.RECTANGLE)
                    g.DrawRectangle(blackpen, m_TempShapes.GetRectangle());
                else if (m_TempShapes.TypeShape == TypeShape.CIRCLE)
                    g.DrawEllipse(blackpen, m_TempShapes.GetRectangle());
                else if (m_TempShapes.TypeShape == TypeShape.LINE)
                    g.DrawLine(blackpen, m_TempShapes.StartupPosition, m_TempShapes.LastPosition);
            }

            g.Dispose();
        }

/*        private void mainMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }*/

        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < m_ListShapes.Count; ++i)
            {
                if (m_ListShapes[i].IsSelected == true)
                {
                    m_ListShapes[i].SColor = m_Color;
                    m_ListShapes[i].TColor = TypeColor.BORDER;
                    m_ListShapes[i].IsSelected = false;
                    m_ListShapes[i].Border_Color = m_Color;
                }
            }
            this.panel1.Refresh();
        }

        private void btn_Exit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btn_DrawingRectangle_Click(object sender, EventArgs e)
        {
            m_Type = TypeShape.RECTANGLE;
            m_IsPointer = false;
            m_IsCopy = false;
        }

        private void btn_DrawingEllilpse_Click(object sender, EventArgs e)
        {
            m_Type = TypeShape.CIRCLE;
            m_IsPointer = false;
            m_IsCopy = false;
        }

        private void btn_DrawingLine_Click(object sender, EventArgs e)
        {
            m_Type = TypeShape.LINE;
            m_IsPointer = false;
            m_IsCopy = false;
        }

        private void btn_Pointer_Click(object sender, EventArgs e)
        {
            m_IsPointer = true;
            m_IsCopy = false;
        }

        private void btn_Delete_Click(object sender, EventArgs e)
        {
            if (m_ListShapes.Count != 0)
            {
                for (int i = 0; i < m_ListShapes.Count; ++i)
                {
                    if (m_ListShapes[i].IsSelected == true)
                    {
                        m_ListShapes.RemoveAt(i);
                        this.panel1.Refresh();
                        --i;
                    }
                }
            }
            m_IsCopy = false;
        }

        private void btn_Cut_Click(object sender, EventArgs e)
        {
            if (m_IsPointer == true)
            {
                if (m_ListShapes.Count != 0)
                {
                    for (int i = 0; i < m_ListShapes.Count; ++i)
                    {
                        if (m_ListShapes[i].IsSelected == true)
                        {
                            if (m_TempShapes == null)
                            {
                                if (m_ListShapes[i].TypeShape == TypeShape.RECTANGLE)
                                {
                                    m_Shapes = new CRectangle(m_ListShapes[i].StartupPosition, m_ListShapes[i].LastPosition);
                                  
                                }
                                else if (m_ListShapes[i].TypeShape == TypeShape.CIRCLE)
                                {
                                    m_Shapes = new CEllipse(m_ListShapes[i].StartupPosition, m_ListShapes[i].Width, m_ListShapes[i].Height);
                                }
                                else if (m_ListShapes[i].TypeShape == TypeShape.LINE)
                                {
                                    m_Shapes = new CLine(m_ListShapes[i].StartupPosition, m_ListShapes[i].DeltaX, m_ListShapes[i].DeltaY);
                                }
                                m_Shapes.Border_Color = m_ListShapes[i].Border_Color;
                                m_Shapes.TColor = m_ListShapes[i].TColor;
                                m_Shapes.SColor = m_ListShapes[i].SColor;
                                m_ListShapes.RemoveAt(i);
                                this.panel1.Refresh();
                                break;
                            }
                        }
                    }
                }
                m_IsCut = true;
                m_IsPointer = false;
            }
            m_IsCopy = false;
        }

        private void btn_Copy_Click(object sender, EventArgs e)
        {
            if (m_IsPointer == true)
            {
                if (m_ListShapes.Count != 0)
                {
                    for (int i = 0; i < m_ListShapes.Count; ++i)
                    {
                        if (m_ListShapes[i].IsSelected == true)
                        {
                            if (m_TempShapes == null)
                            {
                                if (m_ListShapes[i].TypeShape == TypeShape.RECTANGLE)
                                {
                                    m_Shapes = new CRectangle(m_ListShapes[i].StartupPosition, m_ListShapes[i].LastPosition);

                                }
                                else if (m_ListShapes[i].TypeShape == TypeShape.CIRCLE)
                                {
                                    m_Shapes = new CEllipse(m_ListShapes[i].StartupPosition, m_ListShapes[i].Width, m_ListShapes[i].Height);
                                }
                                else if (m_ListShapes[i].TypeShape == TypeShape.LINE)
                                {
                                    m_Shapes = new CLine(m_ListShapes[i].StartupPosition, m_ListShapes[i].DeltaX, m_ListShapes[i].DeltaY);
                                }
                                m_Shapes.TColor = m_ListShapes[i].TColor;
                                m_Shapes.SColor = m_ListShapes[i].SColor;
                                m_Shapes.Border_Color = m_ListShapes[i].Border_Color;
                                //m_ListShapes.RemoveAt(i);
                                this.panel1.Refresh();
                                break;
                            }
                        }
                    }
                }
                m_IsCopy = true;
                m_IsPointer = false;
                //m_Type = TypeShape.NONE
            }
        }

        private void btn_Background_Click(object sender, EventArgs e)
        {
            ColorDialog _colorDialog = new ColorDialog();
            if (_colorDialog.ShowDialog() == DialogResult.OK)
            {
                m_ScreenColor = _colorDialog.Color;
                this.panel1.BackColor = m_ScreenColor;
                this.panel1.Refresh();
            }
            m_IsCopy = false;
        }

        private void btn_FC_Click(object sender, EventArgs e)
        {
            ColorDialog _colorDialog = new ColorDialog();
            _colorDialog.ShowDialog();
            m_Color = _colorDialog.Color;
            for (int i = 0; i < m_ListShapes.Count; ++i)
            {
                if (m_ListShapes[i].IsSelected == true)
                    m_ListShapes[i].SColor = m_Color;
                //m_ListShapes[i].IsSelected = false;
            }
            this.panel1.Refresh();
            m_IsCopy = false;
        }

        private void btn_Fill_Click(object sender, EventArgs e)
        {
            
            for (int i = 0; i < m_ListShapes.Count; ++i)
            {
                if (m_ListShapes[i].IsSelected == true && m_ListShapes[i].TypeShape != TypeShape.LINE)
                {
                    m_ListShapes[i].SColor = m_Color;
                    m_ListShapes[i].TColor = TypeColor.FILL;
                    m_ListShapes[i].IsSelected = false;
                }
                
            }
            this.panel1.Refresh();
            m_IsCopy = false;
        }

        private void btn_Sort_Click(object sender, EventArgs e)
        {
            bool isLine = false;
            
            for (int i = 0; i < m_ListShapes.Count; ++i)
            {
                if (m_ListShapes[i].TypeShape == TypeShape.LINE)
                    isLine = true;
            }

            if (isLine)
            {
                MessageBox.Show("Can not sort line, press ok to delete line");
            }

            for (int i = 0; i < m_ListShapes.Count; ++i)
            {
                if (m_ListShapes[i].TypeShape == TypeShape.LINE)
                    m_ListShapes.RemoveAt(i);
            }

            if (m_ListShapes.Count > 1)
            {
                for (int i = 0; i < m_ListShapes.Count - 1; ++i)
                {
                    for (int j = i + 1; j < m_ListShapes.Count; ++j)
                    {
                        if (m_ListShapes[i].GetSupperficies() > m_ListShapes[j].GetSupperficies())
                        {
                            Shapes _temp;
                            _temp = m_ListShapes[i];
                            m_ListShapes[i] = m_ListShapes[j];
                            m_ListShapes[j] = _temp;

                        }
                    }
                }
            }

            if (m_ListShapes.Count > 0)
            {
                int _maxHeight = m_ListShapes[0].Height;
                for (int i = 1; i < m_ListShapes.Count - 1; ++i)
                {
                    _maxHeight = m_ListShapes[i].Height > _maxHeight ? m_ListShapes[i].Height : _maxHeight;
                }

                for (int i = 0; i < m_ListShapes.Count; ++i)
                {
                    bool _isNotFirst = false;
                    if (i == 0)
                    {
                        m_ListShapes[i].StartupPosition = new Point(0, 0);
                    }
                    else if (m_ListShapes[i].TypeShape != TypeShape.LINE)
                    {
                        if (m_ListShapes[i - 1].StartupPosition.X + m_ListShapes[i - 1].Width + 5 + m_ListShapes[i].Width <= this.panel1.Width)
                            m_ListShapes[i].StartupPosition = new Point(m_ListShapes[i - 1].StartupPosition.X + m_ListShapes[i - 1].Width + 5, m_ListShapes[i - 1].StartupPosition.Y);
                        else if (_isNotFirst)
                            m_ListShapes[i].StartupPosition = new Point(m_ListShapes[i - 1].StartupPosition.X + 5, m_ListShapes[i - 1].StartupPosition.Y + m_ListShapes[i - 1].Height + 5);
                        else if (_isNotFirst == false)
                        {
                            m_ListShapes[i].StartupPosition = new Point(0, m_ListShapes[i - 1].StartupPosition.Y + _maxHeight + 5);
                            _isNotFirst = true;
                        }
                    }
                }
            }
            else
            {
                MessageBox.Show("Không có hình nào để sắp xếp!");
            }
            
            this.panel1.Refresh();
            m_IsCopy = false;
        }

        private void btn_Save_Click(object sender, EventArgs e)
        {
            Stream myStream;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            String _fileName = null;
  

            saveFileDialog1.Filter = "Image files (*.png)|*.png|All files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 1;
            saveFileDialog1.RestoreDirectory = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if ((myStream = saveFileDialog1.OpenFile()) != null)
                {
                    _fileName = saveFileDialog1.FileName;
                    myStream.Close();
                }
            }

            int width = this.panel1.Size.Width;
            int height = this.panel1.Size.Height;

            Bitmap bm = new Bitmap(width, height);
            this.panel1.DrawToBitmap(bm, new Rectangle(0, 0, width, height));

            if (_fileName != null)
            {
                bm.Save(_fileName, ImageFormat.Png);
                MessageBox.Show("Saved !!");
            }
        }

        private void btn_Paste_Click(object sender, EventArgs e)
        {

        }
    }
}
